package logic

import (
	"context"
	"fmt"
	"log"
	"shop-manager/internal/do"
	"shop-manager/internal/repos/salesperson"
	"shop-manager/internal/repos/supermarket"
	"shop-manager/internal/vo"

	"github.com/samber/lo"
)

//go:generate newc
type SalesPersonLogic struct {
	salesPersonRepo *salesperson.SalesPersonRepo
	supermarketRepo *supermarket.SupermarketRepo
}

func (l *SalesPersonLogic) CreateSalesPerson(ctx context.Context, req vo.CreateSalesPersonReq) (*vo.CreateSalesPersonRsp, error) {
	ss, _, err := l.supermarketRepo.List(ctx, supermarket.ListParam{
		IDs: []int{req.SupermarketID},
	})
	if err != nil {
		return nil, err
	}
	if len(ss) == 0 {
		return nil, fmt.Errorf("supermarket not found, id:%v", req.SupermarketID)
	}
	id, err := l.salesPersonRepo.Create(ctx, &do.SalesPerson{
		Name:          req.Name,
		Note:          req.Note,
		SupermarketID: req.SupermarketID,
		BasicSalary:   req.BasicSalary,
	})
	if err != nil {
		return nil, err
	}

	return &vo.CreateSalesPersonRsp{
		ID: id,
	}, nil
}

type ListSalesPersonRsp struct {
	Items []*vo.ListSalesPersonRspItem
	Total int64
}

// list
func (l *SalesPersonLogic) ListSalesPerson(ctx context.Context, req vo.ListSalesPersonReq) (*ListSalesPersonRsp, error) {
	listData, total, err := l.salesPersonRepo.List(ctx, salesperson.ListParam{
		Page:           req.Page,
		PageSize:       req.PageSize,
		Search:         req.Search,
		Sorts:          req.Sorts,
		SupermarketIDs: req.SupermarketIDs,
	})
	if err != nil {
		return nil, err
	}

	supermarketIds := lo.Map(listData, func(item *do.SalesPerson, index int) int {
		return item.SupermarketID
	})
	ss, _, err := l.supermarketRepo.List(ctx, supermarket.ListParam{
		IDs: supermarketIds,
	})
	if err != nil {
		return nil, err
	}
	// superMarketId => superMarket
	superMarketMap := lo.Associate(ss, func(item *do.Supermarket) (int, *do.Supermarket) {
		return item.ID, item
	})

	retItems := lo.Map(listData, func(item *do.SalesPerson, index int) *vo.ListSalesPersonRspItem {
		var superMarketName string
		if superMarket, ok := superMarketMap[item.SupermarketID]; ok {
			superMarketName = superMarket.Name
		} else {
			log.Printf("supermarket not found, id:%v", item.SupermarketID)
		}
		return &vo.ListSalesPersonRspItem{
			ID:              item.ID,
			Name:            item.Name,
			Note:            item.Note,
			BasicSalary:     item.BasicSalary,
			SupermarketID:   item.SupermarketID,
			SupermarketName: superMarketName,
		}
	})

	return &ListSalesPersonRsp{
		Items: retItems,
		Total: total,
	}, nil
}
